package com.onpositive.wiki3.db.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;

import com.carrotsearch.hppc.IntOpenHashSet;
import com.onpositive.wiki2.whole.model.ITemplateAccess;
import com.onpositive.wiki3.db.IWikiDB;
import com.onpositive.wiki3.db.impl.MajorTemplatesBuilder.TemplateInfo;

public class CategoryVisitor {

	IWikiDB db;

	static class CategoryInfo {
		String title;
		double childRatio;
		double tRatio;
		HashSet<String> tClasses = new HashSet<String>();
		boolean filled;
		int level;
		int id;
		public CategoryInfo(int id){
			this.id=id;
		}
		
		HashMap<String, CategoryInfo> infos = new HashMap<String, CategoryVisitor.CategoryInfo>();
		IntOpenHashSet is = new IntOpenHashSet();
	}

	CategoryInfo info;
	private ITemplateAccess temlates;

	public CategoryVisitor(IWikiDB db) {
		this.db = db;
		temlates = db.getTemlates();
	}

	public IntOpenHashSet build(String root) {
		int id = db.getTitleMapper().getId(root);
		CategoryInfo rs = new CategoryInfo(id);
		rs.title = root;
		fill(id, rs, 0, null);
		HashMap<String, Integer> ms = new HashMap<String, Integer>();
		gatherTemplates(rs, ms);
		String rsa = root;
		if (rsa.endsWith("ies")) {
			rsa = rsa.substring(0, rsa.length() - 3);
		}
		if (rsa.endsWith("s")) {
			rsa = rsa.substring(0, rsa.length() - 1);
		}
		rsa = rsa.toLowerCase();
		ArrayList<TemplateInfo> im = new ArrayList<MajorTemplatesBuilder.TemplateInfo>();
		for (String s : ms.keySet()) {
			System.out.println(s + ":" + ms.get(s));
			TemplateInfo ii = new TemplateInfo(s);

			ii.count = ms.get(s);
			if (ii.str.toLowerCase().contains(rsa)) {
				ii.count *= 4;
			}
			if (ii.str.toLowerCase().contains("infobox")) {
				ii.count *= 2;
			}
			im.add(ii);
		}
		Collections.sort(im);
		int tt = 0;
		for (TemplateInfo m : im) {
			tt += m.count;
		}
		HashSet<String> msa = new HashSet<String>();
		int qt = 0;
		for (TemplateInfo i : im) {
			msa.add(i.str);
			qt += i.count;
			if (tt - qt < tt / 5) {
				break;
			}
		}
		System.out.println(msa);
		HashMap<String, HashSet<String>> incompatibles = new HashMap<String, HashSet<String>>();
		for (String s : msa) {
			for (String sa : msa) {
				if (s != sa) {
					int templateNum = temlates.getTemplateNum(s);
					int templateNum1 = temlates.getTemplateNum(sa);
					int[] pages = temlates.getPages(templateNum);
					int[] pages1 = temlates.getPages(templateNum1);
					IntOpenHashSet m = new IntOpenHashSet();
					int k = 0;
					if (pages1.length > pages.length) {
						m.add(pages1);

						for (int z : pages) {
							if (m.contains(z)) {
								k++;
							}
						}

					} else {
						m.add(pages);
						for (int z : pages1) {
							if (m.contains(z)) {
								k++;
							}
						}
					}
					if (k < 3) {
						HashSet<String> hashSet = incompatibles.get(s);
						if (hashSet == null) {
							hashSet = new HashSet<String>();
							incompatibles.put(s, hashSet);
						}
						hashSet.add(sa);
					}
				}
			}
		}
		System.out.println(msa);
		if (!incompatibles.isEmpty()) {
			throw new RuntimeException("Bad category");
		}
		IntOpenHashSet mm=new IntOpenHashSet();
		fill(rs,msa,mm);
		return mm;
		
		// for (Te)
	}

	private void fill(CategoryInfo rs, HashSet<String> msa, IntOpenHashSet mm) {
		if (rs.filled){
			
		}
	}

	private void gatherTemplates(CategoryInfo rs, HashMap<String, Integer> ms) {
		for (int i : rs.is.toArray()) {
			String[] templates = temlates.getTemplates(i);
			for (String m : templates) {
				Integer integer = ms.get(m);
				if (integer == null) {
					integer = 0;
				}
				ms.put(m, integer + 1);
			}
		}
		for (CategoryInfo i : rs.infos.values()) {
			gatherTemplates(i, ms);
		}
	}

	private void fill(int id, CategoryInfo rs, int i, CategoryInfo parent) {
		int[] categoryMembers = db.getCategoryAccessor().getCategoryMembers(id,
				false);
		int m = 0;
		int tcount = 0;
		rs.level = i;
		IntOpenHashSet os = new IntOpenHashSet();
		for (int c : categoryMembers) {
			boolean hasText = db.getContentAccessor().hasText(c);
			if (hasText) {
				m++;
				String[] templates = temlates.getTemplates(c);

				if (templates.length > 0) {
					tcount++;
					count++;
					rs.is.add(c);
				}
				rs.tClasses.addAll(Arrays.asList(templates));
			} else {
				os.add(c);
			}
		}
		doFill(rs, i, categoryMembers, m, tcount, os);
	}

	int count;

	protected void doFill(CategoryInfo rs, int i, int[] categoryMembers, int m,
			int tcount, IntOpenHashSet os) {
		rs.filled = true;
		rs.childRatio = m / (double) categoryMembers.length;
		rs.tRatio = tcount / (double) categoryMembers.length;

		for (int c : os.toArray()) {
			CategoryInfo mm = new CategoryInfo(c);
			mm.title = db.getTitleMapper().getTitle(c);
			rs.infos.put(mm.title, mm);
			if (i < 2 && count < 2000) {
				fill(c, mm, i + 1, rs);
			}
		}
	}
}
